home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / applications / wp / chinesetex.lha / netpbm / src / pbmtopk.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-20  |  29.8 KB  |  955 lines

  1. /*
  2.   pbmtopk, adapted from "pxtopk.c by tomas rokicki" by AJCD 1/8/90
  3.   
  4.   compile with: cc -o pbmtopk pbmtopk.c -lm -lpbm
  5.   */
  6.  
  7. /*
  8.   Modified by David Fong so as to be compilable by Amiga GCC.
  9.  
  10.   Line changed from...
  11.  
  12.     if (sscanf(here,"%s%n",str,&n) != 1))
  13.  
  14.   to...
  15.  
  16.     a=sscanf(here,"%s%n",str,&n);
  17.     if (a != 1)
  18.  
  19.   For some strange reason, the first version ALWAYS fails, even
  20.   if the .opt file line is valid.
  21.  
  22.   */
  23.  
  24. /*
  25.   Further modified by David Fong to accept separate x and y resolutions 20-Jan-95
  26.  
  27.   designunits(p) replaced by xdesignunits(p) and ydesignunits(p)
  28.   resolutions    replaced by xresolution     and yresolution
  29.   hppp           replaced by xhppp           and yhppp
  30.  
  31.   */
  32.  
  33. #include <stdio.h>
  34. #include <math.h>
  35. #include <ctype.h>
  36. #include "pbm.h"
  37. #include "libpbm1.c"
  38. #include "libpbm2.c"
  39. #include "libpbm3.c"
  40. #include "libpbm4.c"
  41. #include "libpbm5.c"
  42.  
  43. #define MAXPKCHAR 256
  44. #define MAXOPTLINE 200
  45. #define MAXWIDTHTAB 256
  46. #define MAXHEIGHTTAB 16
  47. #define MAXDEPTHTAB 16
  48. #define MAXITALICTAB 64
  49. #define MAXPARAMS 30
  50. #define NAMELENGTH 80
  51.  
  52. #define round(a) ((int)(a+.5))
  53. #define fixword(d) ((int)((double)(d)*1048576))
  54. #define unfixword(f) ((double)(f) / 1048576)
  55. #define fixrange(f) ((f) < 16777216 && (f) > -16777216)
  56. #define xdesignunits(p) ((p)*72.27/(double)xresolution/unfixword(designsize))
  57. #define ydesignunits(p) ((p)*72.27/(double)yresolution/unfixword(designsize))
  58.  
  59. /* character flags: in order of appearance in option files. */
  60. #define XOFFSET     1
  61. #define YOFFSET     2
  62. #define HORZESC     4
  63. #define VERTESC     8
  64. #define TFMWIDTH   16
  65. #define TFMHEIGHT  32
  66. #define TFMDEPTH   64
  67. #define TFMITALIC 128
  68.  
  69. typedef int integer ;
  70. typedef char quarterword ;
  71. typedef char boolean ;
  72. typedef quarterword ASCIIcode ;
  73. typedef quarterword eightbits ;
  74. typedef unsigned char byte ;
  75.  
  76. integer xresolution, yresolution, designsize ;
  77. char *filename[MAXPKCHAR] ;
  78.  
  79. integer xoffset[MAXPKCHAR] ;
  80. integer yoffset[MAXPKCHAR] ;
  81. integer horzesc[MAXPKCHAR] ;
  82. integer vertesc[MAXPKCHAR] ;
  83.  
  84. byte tfmindex[MAXPKCHAR] ;
  85. byte hgtindex[MAXPKCHAR] ;
  86. byte depindex[MAXPKCHAR] ;
  87. byte italindex[MAXPKCHAR] ;
  88. byte charflags[MAXPKCHAR] ;
  89.  
  90. bit **bitmap ;
  91. integer smallestch = MAXPKCHAR ;
  92. integer largestch = -1;
  93. integer emwidth  = 0;
  94. integer checksum ;
  95. char *codingscheme = "GRAPHIC" ;
  96. char *familyname = "PBM" ;
  97.  
  98. integer widthtab[MAXWIDTHTAB] = {0}; /* TFM widths */
  99. integer numwidth = 1;      /* number of entries in width table */
  100. integer heighttab[MAXHEIGHTTAB]  = {0};
  101. integer numheight = 1;
  102. integer depthtab[MAXDEPTHTAB] = {0};
  103. integer numdepth = 1;
  104. integer italictab[MAXITALICTAB] = {0};
  105. integer numitalic = 1;
  106. integer parameters[MAXPARAMS] = {0};
  107. integer numparam = 0;
  108.  
  109. static ASCIIcode xord[128] ;
  110. static char xchr[256] = {
  111.    '?', '?', '?', '?', '?', '?', '?', '?',
  112.    '?', '?', '?', '?', '?', '?', '?', '?',
  113.    '?', '?', '?', '?', '?', '?', '?', '?',
  114.    '?', '?', '?', '?', '?', '?', '?', '?',
  115.    ' ', '!', '"', '#', '$', '%', '&', '\'',
  116.    '(', ')', '*', '+', ',', '-', '.', '/',
  117.    '0', '1', '2', '3', '4', '5', '6', '7',
  118.    '8', '9', ':', ';', '<', '=', '>', '?',
  119.    '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
  120.    'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
  121.    'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
  122.    'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
  123.    '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
  124.    'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
  125.    'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
  126.    'x', 'y', 'z', '{', '|', '}', '~', '?' };
  127.  
  128. static FILE *tfmfile, *pkfile ;
  129. static char tfmname[NAMELENGTH+1], pkname[NAMELENGTH+1] ;
  130. static integer pbmtopk_pkloc = 0 ;
  131. static integer bitweight ;
  132. static integer outputbyte ;
  133. static integer car ;
  134. static integer xhppp, yhppp ;
  135. static integer width ;
  136. static integer height ;
  137.  
  138. /* checksum not computed at the moment
  139. static integer compute_checksum()
  140. {
  141.      begin
  142.      c0:=bc; c1:=ec; c2:=bc; c3:=ec;
  143.      for c:=bc to ec do if char_wd[c]>0 then
  144.      begin
  145.      temp_width:=memory[char_wd[c]];
  146.      if design_units<>unity then
  147.      temp_width:=round((temp_width/design_units)*1048576.0);
  148.      temp_width:=temp_width + (c+4)*@'20000000; {this should be positive}
  149.      c0:=(c0+c0+temp_width) mod 255;
  150.      c1:=(c1+c1+temp_width) mod 253;
  151.      c2:=(c2+c2+temp_width) mod 251;
  152.      c3:=(c3+c3+temp_width) mod 247;
  153.      end;
  154.      header_bytes[check_sum_loc]:=c0;
  155.      header_bytes[check_sum_loc+1]:=c1;
  156.      header_bytes[check_sum_loc+2]:=c2;
  157.      header_bytes[check_sum_loc+3]:=c3;
  158.      end
  159. }
  160. */
  161.  
  162. #define add_tfmwidth(v) (add_tfmtable(widthtab, &numwidth, v, MAXWIDTHTAB,\
  163.                                       "TFM width"))
  164. #define add_tfmheight(v) (add_tfmtable(heighttab, &numheight, v, MAXHEIGHTTAB,\
  165.                                        "TFM height"))
  166. #define add_tfmdepth(v) (add_tfmtable(depthtab, &numdepth, v, MAXDEPTHTAB,\
  167.                                       "TFM depth"))
  168. #define add_tfmitalic(v) (add_tfmtable(italictab, &numitalic, v, MAXITALICTAB,\
  169.                                        "Italic correction"))
  170. static byte
  171. add_tfmtable(table, count, value, max_count, name)
  172.      integer *table, *count, value, max_count;
  173.      char *name;
  174. {
  175.    integer i;
  176.    for (i = 0; i < *count; i++) /* search for value in tfm table */
  177.       if (table[i] == value) return (byte)i;
  178.    if (*count >= max_count)
  179.       pm_error("too many values in %s table", name) ;
  180.    if (!fixrange(value))
  181.       pm_error("%s %f for char %d out of range",
  182.                name, unfixword(value), car);
  183.    table[*count] = value ;
  184.    return (*count)++ ;
  185. }
  186.  
  187. /* add a suffix to a filename in an allocated space */
  188. static void pbmtopk_add_suffix(name, suffix)
  189.      char *name, *suffix ;
  190. {
  191.    char *slash = rindex(name, '/');
  192.    char *dot = rindex(name, '.');
  193.  
  194.    if ((dot && slash ? dot < slash : !dot) && strcmp(name, "-"))
  195.       strcat(name, suffix);
  196. }
  197.  
  198. /* initialize the PK parameters */
  199. static void initialize_pk()
  200. {
  201.    integer i ;
  202.    pm_message("This is PBMtoPK, version 2.4, modified by David Fong 20-Jan-95.") ;
  203.    for (i = 127 ; i <= 255 ; i ++) xchr[i] = '?' ;
  204.    for (i = 0 ; i <= 127 ; i ++) xord[i] = 32 ;
  205.    for (i = 32 ; i < 127 ; i ++) xord[(int)xchr[i]] = i ;
  206.    for (i = 0; i < MAXPKCHAR; i++) {
  207.       filename[i] = NULL;
  208.       charflags[i] = 0;
  209.    }
  210.    designsize = fixword(1.0) ;
  211. }
  212.  
  213. /* write a single byte to the PK file */
  214. static void pbmtopk_pkbyte(b)
  215.      integer b ;
  216. {
  217.    if (b < 0) b += 256 ;
  218.    putc(b, pkfile) ;
  219.    pbmtopk_pkloc++ ;
  220. }
  221.  
  222. /* write two bytes to the PK file */
  223. static void pkhalfword(a)
  224.      integer a ;
  225. {
  226.    if (a < 0) a += 65536 ;
  227.    pbmtopk_pkbyte(a >> 8) ;
  228.    pbmtopk_pkbyte(a & 255) ;
  229. }
  230.  
  231. /* write three bytes to the PK file */
  232. static void pkthreebytes(a)
  233.      integer a ;
  234. {
  235.    pbmtopk_pkbyte((a>>16) & 255) ;
  236.    pbmtopk_pkbyte((a>>8) & 255) ;
  237.    pbmtopk_pkbyte(a & 255) ;
  238. }
  239.  
  240. /* write four bytes to the PK file */
  241. static void pkword(a)
  242.      integer a ;
  243. {
  244.    pbmtopk_pkbyte((a>>24) & 255) ;
  245.    pbmtopk_pkbyte((a>>16) & 255) ;
  246.    pbmtopk_pkbyte((a>>8) & 255) ;
  247.    pbmtopk_pkbyte(a & 255) ;
  248. }
  249.  
  250. /* write a nibble to the PK file */
  251. static void pknyb(a)
  252.      integer a ;
  253. {
  254.    if (bitweight == 16) {
  255.       outputbyte = (a<<4) ;
  256.       bitweight = 1 ;
  257.    } else {
  258.       pbmtopk_pkbyte(outputbyte + a) ;
  259.       bitweight = 16 ;
  260.    }
  261. }
  262.  
  263. /* write preamble to PK file */
  264. static void writepreamble()
  265. {
  266.    integer i ;
  267.    char *comment = "PBMtoPK 2.4 output" ;
  268.    
  269.    pbmtopk_pkbyte(247) ;                                /* PRE command */
  270.    pbmtopk_pkbyte(89) ;                         /* PK file type */
  271.    pbmtopk_pkbyte(strlen(comment)) ;                    /* output comment */
  272.    for (i = 0 ; i < strlen(comment); i++) pbmtopk_pkbyte(xord[(int)comment[i]]) ;
  273.    pkword(designsize) ;                         /* write designsize */
  274.    pkword(checksum) ;           /* write checksum; calculate if possible */
  275.    pkword(xhppp) ;                              /* write H pixels per point */
  276.    pkword(yhppp) ;                              /* write V pixels per point */
  277. }
  278.  
  279. /* write postamble to PK file, padded to word length */
  280. static void writepostamble()
  281. {
  282.    pbmtopk_pkbyte(245) ;                                /* POST command */
  283.    while (pbmtopk_pkloc % 4)
  284.       pbmtopk_pkbyte(246) ;                             /* pad with no-ops */
  285.    pm_message("%d bytes written to packed file.", pbmtopk_pkloc) ;
  286. }
  287.  
  288. /* write a byte to the TFM file */
  289. static void tfmbyte(b)
  290.      integer b ;
  291. {
  292.    if (b < 0) b += 256 ;
  293.    putc(b, tfmfile) ;
  294. }
  295.  
  296. /* write a half word to the TFM file */
  297. static void tfmhalfword(a)
  298.      integer a ;
  299. {
  300.    if (a < 0) a += 65536 ;
  301.    tfmbyte(a >> 8) ;
  302.    tfmbyte(a & 255) ;
  303. }
  304.  
  305. /* write a word to the TFM file */
  306. static void tfmword(a)
  307.      integer a ;
  308. {
  309.    tfmbyte((a>>24) & 255) ;
  310.    tfmbyte((a>>16) & 255) ;
  311.    tfmbyte((a>>8) & 255) ;
  312.    tfmbyte(a & 255) ;
  313. }
  314.  
  315. /* write the whole TFM file for the font */
  316. static void writetfmfile()
  317. {
  318.    integer totallength ;
  319.    integer headersize = 17;
  320.    integer i ;
  321.    
  322.    if (largestch - smallestch < 0) {
  323.       largestch = 0;
  324.       smallestch = 1;
  325.    }
  326.    if (numparam < 7) /* set default parameters */
  327.       switch (numparam) {
  328.       case 0: /* slant */
  329.          parameters[numparam++] = 0 ;
  330.       case 1: /* space */
  331.          parameters[numparam++] = fixword(xdesignunits(emwidth/3.0));
  332.       case 2: /* space_stretch */
  333.          parameters[numparam++] = fixword(unfixword(parameters[1])/2.0) ;
  334.       case 3: /* space_shrink */
  335.          parameters[numparam++] = fixword(unfixword(parameters[1])/3.0) ;
  336.       case 4: /* x_height */
  337.          parameters[numparam++] = fixword(0.45);
  338.       case 5: /* quad */
  339.          parameters[numparam++] = fixword(xdesignunits(emwidth)) ;
  340.       case 6: /* extra_space */
  341.          parameters[numparam++] = fixword(unfixword(parameters[1])/3.0) ;
  342.       }
  343.    totallength = 6 + headersize + (largestch+1-smallestch) +
  344.       numwidth + numheight + numdepth + numitalic + numparam ;
  345.    /* lengths */
  346.    tfmhalfword(totallength) ;                   /* write file TFM length */
  347.    tfmhalfword(headersize) ;                    /* write TFM header length */
  348.    tfmhalfword(smallestch) ;                    /* write lowest char index */
  349.    tfmhalfword(largestch) ;                     /* write highest char index */
  350.    tfmhalfword(numwidth) ;                      /* write number of widths */
  351.    tfmhalfword(numheight) ;                     /* write number of heights */
  352.    tfmhalfword(numdepth) ;                      /* write number of depths */
  353.    tfmhalfword(numitalic) ;                     /* write number of italcorrs */
  354.    tfmhalfword(0) ;                             /* lig/kern table */
  355.    tfmhalfword(0) ;                             /* kern table */
  356.    tfmhalfword(0) ;                             /* extensible char table */
  357.    tfmhalfword(numparam) ;                      /* number of fontdimens */
  358.    /* header */
  359.    tfmword(checksum) ;                          /* write checksum */
  360.    tfmword(designsize) ;                        /* write designsize */
  361.    if (strlen(codingscheme) > 39) tfmbyte(39) ; /* write coding scheme len */
  362.    else tfmbyte(strlen(codingscheme)) ;
  363.    for (i = 0; i < 39; i++)                     /* write coding scheme */
  364.       if (*codingscheme) tfmbyte(xord[(int)(*codingscheme++)]) ;
  365.       else tfmbyte(0) ;
  366.    if (strlen(familyname) > 19) tfmbyte(19) ;   /* write family length */
  367.    else tfmbyte(strlen(familyname)) ;
  368.    for (i = 0; i < 19; i++)                     /* write family */
  369.       if (*familyname) tfmbyte(xord[(int)(*familyname++)]) ;
  370.       else tfmbyte(0) ;
  371.    /* char_info */
  372.    for (car = smallestch; car <= largestch; car++)
  373.       if (filename[car]) {                      /* write character info */
  374.          tfmbyte(tfmindex[car]) ;
  375.          tfmbyte((hgtindex[car]<<4) + depindex[car]) ;
  376.          tfmbyte(italindex[car]<<2) ;
  377.          tfmbyte(0) ;
  378.       } else tfmword(0) ;
  379.    /* width table */
  380.    for (i = 0; i < numwidth; i++) tfmword(widthtab[i]) ;
  381.    /* height table */
  382.    for (i = 0; i < numheight; i++) tfmword(heighttab[i]) ;
  383.    /* depth table */
  384.    for (i = 0; i < numdepth; i++) tfmword(depthtab[i]) ;
  385.    /* italic correction table */
  386.    for (i = 0; i < numitalic; i++) tfmword(italictab[i]) ;
  387.    /* no lig_kern, kern, or exten tables */
  388.    /* fontdimen table */
  389.    for (i = 0; i < numparam; i++)
  390.       if (i && !fixrange(parameters[i]))
  391.          pm_error("parameter %d out of range (-p)", i);
  392.       else
  393.          tfmword(parameters[i]) ;
  394.    pm_message("%d bytes written to tfm file.", totallength*4) ;
  395. }
  396.  
  397. /* read a character from a PBM file */
  398. static void readcharacter()
  399. {
  400.    FILE *fp;
  401.    
  402.    fp = pm_openr(filename[car]);
  403.    bitmap = pbm_readpbm(fp, &width, &height) ;
  404.    pm_close(fp) ;
  405.    
  406.    if ((charflags[car] & HORZESC) == 0) horzesc[car] = width ;
  407.    if ((charflags[car] & VERTESC) == 0) vertesc[car] = 0;
  408.    if ((charflags[car] & XOFFSET) == 0) xoffset[car] = 0;
  409.    if ((charflags[car] & YOFFSET) == 0) yoffset[car] = height-1;
  410.    if ((charflags[car] & TFMWIDTH) == 0)
  411.       tfmindex[car] = add_tfmwidth(fixword(xdesignunits(width)));
  412.    if ((charflags[car] & TFMHEIGHT) == 0)
  413.       hgtindex[car] = add_tfmheight(fixword(ydesignunits(yoffset[car]+1)));
  414.    if ((charflags[car] & TFMDEPTH) == 0)
  415.       depindex[car] = add_tfmdepth(fixword(ydesignunits(height-1-yoffset[car])));
  416.    if ((charflags[car] & TFMITALIC) == 0) italindex[car] = 0;
  417.    
  418.    if (car < smallestch) smallestch = car;
  419.    if (car > largestch) largestch = car;
  420.    if (width > emwidth) emwidth = width ;
  421. }
  422.  
  423. /* test if two rows of the PBM are the same */
  424. static int equal(row1, row2)
  425.      bit *row1, *row2 ;
  426. {
  427.    integer i ;
  428.    
  429.    for (i = 0; i < width; i++)
  430.       if (row1[i] != row2[i]) return (0) ;
  431.    return(1) ;
  432. }
  433.  
  434. static void shipcharacter()
  435. {
  436.    integer compsize ;
  437.    integer i, j, k ;
  438.    bit *zerorow, *onesrow ;
  439.    integer *repeatptr, *bitcounts ;
  440.    integer count ;
  441.    integer test ;
  442.    integer curptr, rowptr ;
  443.    integer bitval ;
  444.    integer repeatflag ;
  445.    integer colptr ;
  446.    integer currepeat ;
  447.    integer dynf ;
  448.    integer deriv[14] ;
  449.    integer bcompsize ;
  450.    boolean firston ;
  451.    integer flagbyte ;
  452.    boolean state ;
  453.    boolean on ;
  454.    integer hbit ;
  455.    integer pbit ;
  456.    boolean ron, son ;
  457.    integer rcount, scount ;
  458.    integer ri, si ;
  459.    integer max2 ;
  460.    integer predpkloc ;
  461.    integer buff ;
  462.    
  463.    integer tfwid = widthtab[tfmindex[car]] ;
  464.    integer hesc = horzesc[car] ;
  465.    integer vesc = vertesc[car] ;
  466.    integer xoff = xoffset[car] ;
  467.    integer yoff = yoffset[car] ;
  468.    
  469.    repeatptr =
  470.       (integer *)malloc((unsigned int)((height+1)*sizeof(integer))) ;
  471.    bitcounts =
  472.       (integer *)malloc((unsigned int)((height*width)*sizeof(integer))) ;
  473.    if (repeatptr == NULL || bitcounts == NULL)
  474.       pm_error("out of memory while allocating bit counts");
  475.    zerorow = pbm_allocrow(width) ;              /* initialise plain rows */
  476.    onesrow = pbm_allocrow(width) ;
  477.    for (i = 0 ; i < width ; i++) {
  478.       zerorow[i] = PBM_WHITE ;
  479.       onesrow[i] = PBM_BLACK ;
  480.    }
  481.    for (i=0; i < height; i = k) {               /* set repeat pointers */
  482.       k = i + 1;
  483.       if (!equal(bitmap[i], zerorow) && !equal(bitmap[i], onesrow)) {
  484.          while (k < height && equal(bitmap[i], bitmap[k]))
  485.             k++;
  486.          repeatptr[i] = k - i - 1;
  487.       } else {
  488.          repeatptr[i] = 0;
  489.       }
  490.    }
  491.    repeatptr[height] = 0 ;
  492.    colptr = width - 1 ;
  493.    repeatflag = currepeat = curptr = count = rowptr = 0 ;
  494.    test = PBM_WHITE ;
  495.    do {
  496.       colptr++ ;
  497.       if (colptr == width) {                    /* end of row, get next row */
  498.          colptr = 0 ;
  499.          rowptr = currepeat ;
  500.          if (repeatptr[currepeat] > 0) {
  501.             repeatflag = repeatptr[currepeat] ;
  502.             currepeat += repeatflag ;
  503.             rowptr += repeatflag ;
  504.          }
  505.          currepeat++ ;
  506.       }
  507.       if (rowptr >= height) bitval = -1 ;
  508.       else bitval = bitmap[rowptr][colptr] ;
  509.       if (bitval == test) count++ ;             /* count repeated pixels */
  510.       else {                                    /* end of pixel run */
  511.          bitcounts[curptr++] = count ;
  512.          if (curptr+3 >= height*width)
  513.             pm_error("out of memory while saving character counts");
  514.          count = 1 ;
  515.          test = bitval ;
  516.          if (repeatflag > 0) {
  517.             bitcounts[curptr++] = -repeatflag ;
  518.             repeatflag = 0 ;
  519.          }
  520.       }
  521.    } while (test != -1) ;
  522.    bitcounts[curptr] = 0 ;
  523.    bitcounts[curptr + 1] = 0 ;
  524.    for (i = 1 ; i <= 13 ; i ++) deriv[i] = 0 ;
  525.    i = firston = (bitcounts[0] == 0) ;
  526.    compsize = 0 ;
  527.    while (bitcounts[i] != 0) {                  /* calculate dyn_f */
  528.       j = bitcounts[i] ;
  529.       if (j == -1) compsize++ ;
  530.       else {
  531.          if (j < 0) {
  532.             compsize++ ;
  533.             j = -j ;
  534.          }
  535.          if (j < 209) compsize += 2 ;
  536.          else {
  537.             k = j - 193 ;
  538.             while (k >= 16) {
  539.                k >>= 4 ;
  540.                compsize += 2 ;
  541.             }
  542.             compsize++ ;
  543.          }
  544.          if (j < 14) (deriv[j])-- ;
  545.          else if (j < 209) (deriv[(223 - j) / 15])++ ;
  546.          else {
  547.             k = 16 ;
  548.             while (((k<<4) < j + 3)) k <<= 4 ;
  549.             if (j - k <= 192)
  550.                deriv[(207 - j + k) / 15] += 2 ;
  551.          }
  552.       }
  553.       i++ ;
  554.    }
  555.    bcompsize = compsize ;
  556.    dynf = 0 ;
  557.    for (i = 1 ; i <= 13 ; i ++) {
  558.       compsize += deriv[i] ;
  559.       if (compsize <= bcompsize) {
  560.          bcompsize = compsize ;
  561.          dynf = i ;
  562.       }
  563.    }
  564.    compsize = ((bcompsize + 1)>>1) ;
  565.    if ((compsize > ((height*width+7)>>3)) || (height*width == 0)) {
  566.       compsize = ((height*width+7)>>3) ;
  567.       dynf = 14 ;
  568.    }
  569.    flagbyte = (dynf<<4) ;
  570.    if (firston) flagbyte |= 8 ;
  571.    if (tfwid > 16777215 || tfwid < 0 || hesc < 0 || vesc != 0 ||
  572.        compsize > 196579 || width > 65535 || height > 65535 ||
  573.        xoff > 32767 || yoff > 32767 || xoff < -32768 || yoff < -32768) {
  574.       flagbyte |= 7 ;                           /* long form preamble */
  575.       pbmtopk_pkbyte(flagbyte) ;
  576.       compsize += 28 ;
  577.       pkword(compsize) ;                        /* char packet size */
  578.       pkword(car) ;                             /* character number */
  579.       predpkloc = pbmtopk_pkloc + compsize ;
  580.       pkword(tfwid) ;                           /* TFM width */
  581.       pkword(hesc<<16) ;                        /* horiz escapement */
  582.       pkword(vesc<<16) ;                        /* vert escapement */
  583.       pkword(width) ;                           /* bounding box width */
  584.       pkword(height) ;                          /* bounding box height */
  585.       pkword(xoff) ;                            /* horiz offset */
  586.       pkword(yoff) ;                            /* vert offset */
  587.    } else if (hesc > 255 || width > 255 || height > 255 ||
  588.               xoff > 127 || yoff > 127 || xoff < -128 ||
  589.               yoff < -128 || compsize > 1016) {
  590.       compsize += 13 ;                          /* extended short preamble */
  591.       flagbyte += (compsize>>16) + 4 ;
  592.       pbmtopk_pkbyte(flagbyte) ;
  593.       pkhalfword(compsize & 65535) ;            /* char packet size */
  594.       pbmtopk_pkbyte(car) ;                             /* character number */
  595.       predpkloc = pbmtopk_pkloc + compsize ;
  596.       pkthreebytes(tfwid) ;                     /* TFM width */
  597.       pkhalfword(hesc) ;                        /* horiz escapement */
  598.       pkhalfword(width) ;                       /* bounding box width */
  599.       pkhalfword(height) ;                      /* bounding box height */
  600.       pkhalfword(xoff) ;                        /* horiz offset */
  601.       pkhalfword(yoff) ;                        /* vert offset */
  602.    } else {
  603.       compsize += 8 ;                           /* short form preamble */
  604.       flagbyte = flagbyte + (compsize>>8) ;
  605.       pbmtopk_pkbyte(flagbyte) ;
  606.       pbmtopk_pkbyte(compsize & 255) ;                  /* char packet size */
  607.       pbmtopk_pkbyte(car) ;                             /* character number */
  608.       predpkloc = pbmtopk_pkloc + compsize ;
  609.       pkthreebytes(tfwid) ;                     /* TFM width */
  610.       pbmtopk_pkbyte(hesc) ;                            /* horiz escapement */
  611.       pbmtopk_pkbyte(width) ;                           /* bounding box width */
  612.       pbmtopk_pkbyte(height) ;                          /* bounding box height */
  613.       pbmtopk_pkbyte(xoff) ;                            /* horiz offset */
  614.       pbmtopk_pkbyte(yoff) ;                            /* vert offset */
  615.    }
  616.    if (dynf != 14) {                            /* write packed character */
  617.       bitweight = 16 ;
  618.       max2 = 208 - 15 * dynf ;
  619.       i = firston ;
  620.       while (bitcounts[i] != 0) {
  621.          j = bitcounts[i] ;
  622.          if (j == - 1) pknyb(15) ;
  623.          else {
  624.             if (j < 0) {
  625.                pknyb(14) ;
  626.                j = -j ;
  627.             }
  628.             if (j <= dynf) pknyb(j) ;
  629.             else if (j <= max2) {
  630.                j -= dynf + 1 ;
  631.                pknyb((j >> 4) + dynf + 1) ;
  632.                pknyb((j & 15)) ;
  633.             } else {
  634.                j -= max2 - 15 ;
  635.                k = 16 ;
  636.                while (k <= j) {
  637.                   k <<= 4 ;
  638.                   pknyb(0) ;
  639.                }
  640.                while (k > 1) {
  641.                   k >>= 4 ;
  642.                   pknyb(j / k) ;
  643.                   j = j % k ;
  644.                }
  645.             }
  646.          }
  647.          i++ ;
  648.       }
  649.       if (bitweight != 16) pbmtopk_pkbyte(outputbyte) ;
  650.    } else {                                     /* write bitmap character */
  651.       buff = 0 ;
  652.       pbit = 8 ;
  653.       i = firston ;
  654.       hbit = width ;
  655.       on = ! firston ;
  656.       state = 0 ;
  657.       count = repeatflag = 0 ;
  658.       while ((bitcounts[i] != 0) || state || (count > 0)) {
  659.          if (state) {
  660.             count = rcount ;
  661.             i = ri ;
  662.             on = ron ;
  663.             repeatflag-- ;
  664.          } else {
  665.             rcount = count ;
  666.             ri = i ;
  667.             ron = on ;
  668.          }
  669.          do {
  670.             if (count == 0) {
  671.                if (bitcounts[i] < 0) {
  672.                   if (! state) repeatflag = -bitcounts[i] ;
  673.                   i++ ;
  674.                }
  675.                count = bitcounts[i] ;
  676.                i++ ;
  677.                on = !on ;
  678.             }
  679.             if ((count >= pbit) && (pbit < hbit)) {
  680.                if (on) buff += (1 << pbit) - 1 ;
  681.                pbmtopk_pkbyte(buff) ;
  682.                buff = 0 ;
  683.                hbit -= pbit ;
  684.                count -= pbit ;
  685.                pbit = 8 ;
  686.             } else if ((count < pbit) && (count < hbit)) {
  687.                if (on) buff += (1 << pbit) - (1 << (pbit - count)) ;
  688.                pbit -=  count ;
  689.                hbit -= count ;
  690.                count = 0 ;
  691.             } else {
  692.                if (on) buff += (1 << pbit) - (1 << (pbit - hbit)) ;
  693.                count -= hbit ;
  694.                pbit -= hbit ;
  695.                hbit = width ;
  696.                if (pbit == 0) {
  697.                   pbmtopk_pkbyte(buff) ;
  698.                   buff = 0 ;
  699.                   pbit = 8 ;
  700.                }
  701.             }
  702.          } while (hbit != width) ;
  703.          if (state && (repeatflag == 0)) {
  704.             count = scount ;
  705.             i = si ;
  706.             on = son ;
  707.             state = 0 ;
  708.          } else if (! state && (repeatflag > 0)) {
  709.             scount = count ;
  710.             si = i ;
  711.             son = on ;
  712.             state = 1 ;
  713.          }
  714.       }
  715.       if (pbit != 8) pbmtopk_pkbyte(buff) ;
  716.    }
  717.    if (predpkloc != pbmtopk_pkloc)
  718.       pm_error("bad predicted character length: character %d", car);
  719.    pbm_freerow(zerorow); 
  720.    pbm_freerow(onesrow); 
  721.    free((char *)repeatptr);
  722.    free((char *)bitcounts);
  723. }
  724.  
  725. /* check that character is in valid range */
  726. static void checkchar()
  727. {
  728.    if (car < 0 || car >= MAXPKCHAR)
  729.       pm_error("character must be in range 0 to %d", MAXPKCHAR-1) ;
  730. }
  731.  
  732. /* read character information from an option file */
  733. static void optionfile(name)
  734.      char *name ;
  735. {
  736.    FILE *fp ;
  737.    char buffer[MAXOPTLINE] ;
  738.    long a;
  739.    
  740.    fp = pm_openr(name);
  741.    while (!feof(fp)) {
  742.       char *here = buffer;
  743.       
  744.       if (fgets(buffer, MAXOPTLINE, fp) == NULL) break ;
  745.       while (isspace(*here)) here++ ;
  746.       if (*here && *here == '=') {
  747.          if (sscanf(here+1, "%d", &car) != 1)
  748.             pm_error("bad no option file line %s", buffer) ;
  749.       } else if (*here && *here != '%' && *here != '#') {
  750.          char str[NAMELENGTH] ;
  751.          integer i, n;
  752.          
  753.          checkchar() ;
  754.           a=sscanf(here,"%s%n",str,&n);
  755.           if (a != 1)
  756.              pm_error("bad sp option file line %s,%s,%n", buffer, str, a) ;
  757.          filename[car] =
  758.             (char *)malloc((unsigned int)(sizeof(char)*(strlen(str)+1))) ;
  759.          if (filename[car] == NULL)
  760.             pm_error("out of memory allocating filename %s", str);
  761.          strcpy(filename[car], str) ;
  762.          for (i = 1; i < 256; i<<=1) {
  763.             here += n;
  764.             if (sscanf(here, "%s%n", str, &n) != 1) break ;
  765.             if (strcmp(str, "*")) {
  766.                charflags[car] |= i ;
  767.                switch (i) {
  768.                case XOFFSET:
  769.                   xoffset[car] = atoi(str) ;
  770.                   break ;
  771.                case YOFFSET:
  772.                   yoffset[car] = atoi(str) ;
  773.                   break ;
  774.                case HORZESC:
  775.                   horzesc[car] = atoi(str) ;
  776.                   break ;
  777.                case VERTESC:
  778.                   vertesc[car] = atoi(str) ;
  779.                   break ;
  780.                case TFMWIDTH:
  781.                   tfmindex[car] = add_tfmwidth(fixword(atof(str))) ;
  782.                   break ;
  783.                case TFMHEIGHT:
  784.                   hgtindex[car] = add_tfmheight(fixword(atof(str))) ;
  785.                   break ;
  786.                case TFMDEPTH:
  787.                   depindex[car] = add_tfmdepth(fixword(atof(str))) ;
  788.                   break ;
  789.                case TFMITALIC:
  790.                   italindex[car] = add_tfmitalic(fixword(atof(str))) ;
  791.                   break ;
  792.                }
  793.             }
  794.          }
  795.          car++ ;
  796.       }
  797.    }
  798.    pm_close(fp) ;
  799. }
  800.  
  801. int
  802. main(argc, argv)
  803.      int argc ;
  804.      char *argv[] ;
  805. {
  806.    integer i, hesc, vesc, xoff, yoff, tfwid, tfdep, tfhgt, tfital ;
  807.    byte flags ;
  808.    char *usage = "pkfile[.pk] tfmfile[.tfm] xdpi ydpi [-s designsize]\n\
  809.         [-p num param...] [-C codingscheme ] [-F family] [-c num | <char>]...\n\
  810.    <char> is:\n\
  811.         [-W tfmwidth] [-H tfmheight] [-D tfmdepth] [-I ital_corr] [-h horiz]\n\
  812.         [-v vert] [-x xoffset] [-y yoffset] file\n\
  813.     or:\n\
  814.         -f optfile\n" ;
  815.  
  816.    pbm_init(&argc, argv);
  817.    initialize_pk() ;
  818.    
  819.    if (--argc < 1) pm_usage(usage) ;
  820.    strcpy(pkname, *++argv) ;
  821.    pbmtopk_add_suffix(pkname, ".pk") ;
  822.    
  823.    if (--argc < 1) pm_usage(usage) ;
  824.    strcpy(tfmname, *++argv) ;
  825.    pbmtopk_add_suffix(tfmname, ".tfm") ;
  826.  
  827.    /* following few lines changed variable `resolution'
  828.       to `xresolution' */
  829.    
  830.    if (--argc < 1) pm_usage(usage) ;
  831.    xresolution = atoi(*++argv) ;
  832.    if (xresolution < 1 || xresolution > 32767)
  833.       pm_error("unlikely x-resolution %d dpi", xresolution);
  834.   
  835.    /* following lines added by David Fong to allow separate
  836.       x and y resolution.  As a result, the y resolution is a new
  837.       obligatory argument when calling pbmtopk */
  838.  
  839.    if (--argc < 1) pm_usage(usage) ;
  840.    yresolution = atoi(*++argv) ;
  841.    if (yresolution < 1 || yresolution > 32767)
  842.       pm_error("unlikely y-resolution %d dpi", yresolution);
  843.  
  844.    car = flags = hesc = vesc = xoff = yoff = tfwid = 0;
  845.    while (++argv, --argc) {
  846.       if (argv[0][0] == '-' && argv[0][1]) {
  847.          char c, *p;
  848.          c = argv[0][1] ;
  849.          if (argv[0][2]) p = *argv + 2 ;        /* set argument pointer */
  850.          else if (++argv, --argc) p = *argv ;
  851.          else pm_usage(usage) ;
  852.          switch (c) {
  853.          case 'C':
  854.             codingscheme = p;
  855.             break ;
  856.          case 'F':
  857.             familyname = p;
  858.             break ;
  859.          case 'c':
  860.             car = atoi(p) ;
  861.             break ;
  862.          case 's':
  863.             designsize = fixword(atof(p));
  864.             if (designsize < 1048576)
  865.                pm_error("design size %f out of range", unfixword(designsize));
  866.          case 'h':
  867.             hesc = atoi(p) ;
  868.             flags |= HORZESC ;
  869.             break ;
  870.          case 'v':
  871.             vesc = atoi(p) ;
  872.             flags |= VERTESC ;
  873.             break ;
  874.          case 'x':
  875.             xoff = atoi(p) ;
  876.             flags |= XOFFSET ;
  877.             break ;
  878.          case 'y':
  879.             yoff = atoi(p) ;
  880.             flags |= YOFFSET ;
  881.             break ;
  882.          case 'W':
  883.             tfwid = fixword(atof(p)) ;
  884.             flags |= TFMWIDTH ;
  885.             break ;
  886.          case 'H':
  887.             tfhgt = fixword(atof(p)) ;
  888.             flags |= TFMHEIGHT ;
  889.             break ;
  890.          case 'D':
  891.             tfdep = fixword(atof(p)) ;
  892.             flags |= TFMDEPTH ;
  893.             break ;
  894.          case 'I':
  895.             tfital = fixword(atof(p)) ;
  896.             flags |= TFMITALIC ;
  897.             break ;
  898.          case 'f':
  899.             optionfile(p) ;
  900.             break ;
  901.          case 'p':
  902.             numparam = atoi(p);
  903.             if (numparam < 1 || numparam > MAXPARAMS)
  904.                pm_error("parameter count %d out of range", numparam);
  905.             for (i=0; i<numparam; i++)
  906.                if (++argv,--argc)
  907.                   parameters[i] = fixword(atof(*argv)) ;
  908.                else
  909.                   pm_error("not enough parameters (-p)");
  910.             break ;
  911.          default:
  912.             pm_usage(usage) ;
  913.          }
  914.       } else  {
  915.          checkchar() ;
  916.          if (flags & TFMWIDTH)
  917.             tfmindex[car] = add_tfmwidth(tfwid);
  918.          if (flags & TFMDEPTH)
  919.             depindex[car] = add_tfmdepth(tfdep);
  920.          if (flags & TFMHEIGHT)
  921.             hgtindex[car] = add_tfmheight(tfhgt);
  922.          if (flags & TFMITALIC)
  923.             italindex[car] = add_tfmitalic(tfital);
  924.          horzesc[car] = hesc ;
  925.          vertesc[car] = vesc ;
  926.          xoffset[car] = xoff ;
  927.          yoffset[car] = yoff ;
  928.          filename[car] = *argv ;
  929.          charflags[car] = flags ;
  930.          car++ ;
  931.          flags = 0;
  932.       }
  933.    }
  934.    /* following two lines changed to allow separate
  935.       x and y resolutions.  variable hppp replaced
  936.       by variables xhppp and yhppp */
  937.  
  938.    xhppp = round((xresolution<<16) / 72.27) ;
  939.    yhppp = round((yresolution<<16) / 72.27) ;
  940.    pkfile = pm_openw(pkname);
  941.    tfmfile = pm_openw(tfmname);
  942.    writepreamble() ;
  943.    for (car = 0 ; car < MAXPKCHAR ; car++)
  944.       if (filename[car]) {
  945.          readcharacter() ;
  946.          shipcharacter() ;
  947.       }
  948.    writepostamble() ;
  949.    writetfmfile() ;
  950.    pm_close(pkfile) ;
  951.    pm_close(tfmfile) ;
  952.    exit(0);
  953. }
  954.  
  955.